#include "GeoTiffReader.hxx"

GeoTiffReader::GeoTiffReader()
{
	_geoTiffImage = 0;
	_justReadHeader = false;
	_fileName[0] = '\0';
}

GeoTiffReader::~GeoTiffReader()
{
}

void GeoTiffReader::readImage()
{

	TIFF *tif = TIFFOpen(_fileName, "r");

	readHeader(tif);
	if( !_justReadHeader )	readData(tif);

	TIFFClose(tif);
}

void GeoTiffReader::readHeader(TIFF* tif)
{
	unsigned int width = 0;
	unsigned int height = 0;
	unsigned int depth = 0;
	unsigned int channels = 0;

	TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);           // uint32 width;
	TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);        // uint32 height;
	TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &depth);
	TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &channels);

	_geoTiffImage->setWidth(width);
	_geoTiffImage->setHeight(height);
	_geoTiffImage->setDepth(depth);
	_geoTiffImage->setChannels(channels);

	int count = 0;
	double* scale;

	TIFFGetField(tif, 33550, &count, &scale);
	printf("%3.15f,%3.15f,%3.15f\n", scale[0], scale[1], scale[2]);
	_geoTiffImage->setGeoScale(scale[0], scale[1], scale[2]);

	double* tval;
	TIFFGetField(tif, 33922, &count, &tval);
	printf("%3.13f,%3.13f,%3.13f,%3.13f,%3.13f,%3.13f\n", tval[0], tval[1], tval[2], tval[3], tval[4], tval[5], tval[6]);
	_geoTiffImage->setGeoControlPoint(tval);	
}

void GeoTiffReader::readData(TIFF* tif)
{
	int isTiled = TIFFIsTiled(tif);
	
	_geoTiffImage->refreshDataSpace();

	if (isTiled)
	{
		uint32 tileWidth, tileHeight, tileSize;

		int height = _geoTiffImage->getHeight();
		int width = _geoTiffImage->getWidth();
		int channels = _geoTiffImage->getChannels();
		int depth = _geoTiffImage->getDepth();

		uint32 x, y;
		tdata_t buf;

		TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
		TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileHeight);

		tileSize = TIFFTileSize(tif);

		_geoTiffImage->setTiled(true);
		_geoTiffImage->setTileWidth(tileWidth);
		_geoTiffImage->setTileHeight(tileHeight);
		_geoTiffImage->setTileSize(tileSize);

		buf = _TIFFmalloc( tileSize );
		for (y = 0; y < height; y += tileHeight)
			for (x = 0; x < width; x += tileWidth)
			{
				TIFFReadTile(tif, buf, x, y, 0, 0);

				//memcpy(image->imageData, buf, tileWidth * tileLength * channels);
				//cvSplit(image, r, g, b, a);
				//cvMerge(b, g, r, a, image);
				//cvShowImage("TestTile", image);
				//cvWaitKey(20);

				for (int v = 0; v < tileHeight; v++)
				{
					if (y + v >= height) break;

					unsigned int offset = ((y + v) * width + x) * channels * (depth / 8);

					if (x + tileWidth < width)
						memcpy(_geoTiffImage->getImageData() + offset, (unsigned char*)buf + v * tileWidth * channels * (depth / 8 ), tileWidth * channels * ( depth / 8));
					else
						memcpy(_geoTiffImage->getImageData() + offset, (unsigned char*)buf + v * tileWidth * channels * (depth / 8 ), (width - x) * channels * (depth / 8));
				}
			}
		_TIFFfree(buf);
	}
	else
	{
		//int stripsNumber = 0;
		//stripsNumber = TIFFNumberOfStrips(tif);
		//scanlineSize = TIFFScanlineSize(tif);

		//uint32 imagelength;
		//unsigned char* buf;
		//uint32 row;

		//TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imagelength);
		//int ssize = TIFFScanlineSize(tif);
		//buf = (unsigned char*)_TIFFmalloc(ssize);

		//int rowStart = (imagelength - SQUARE_WIDTH) / 2;
		//int colStart = (width - SQUARE_WIDTH) / 2;
		//unsigned char* offset = buf + colStart * 4;

		//for (row = rowStart; row < rowStart + SQUARE_WIDTH; row++)
		//{
		//	TIFFReadScanline(tif, buf, row);

		//	unsigned char* pdata = (unsigned char*)image->imageData + (row - rowStart) * image->widthStep;
		//	memcpy(pdata, buf, image->widthStep);
		//	//printf("Read Scan Line [%d]\n", row);
		//}
		//_TIFFfree(buf);
	}

	extractMaxMinValue();
}

void GeoTiffReader::extractMaxMinValue()
{
	float vmin = 10000;
	float vmax = -10000.0f;

	if (_geoTiffImage->getDepth() == 32 && _geoTiffImage->getChannels() == 1)
	{

		int height = _geoTiffImage->getHeight();
		int width = _geoTiffImage->getWidth();

		float* imageData = (float*)_geoTiffImage->getImageData();

		for (int y = 0; y < height; y++)
		{
			for (int x = 0; x < width; x++)
			{
				float* val = imageData + y * width + x;

				if (*val == -32767.0) continue;

				if (*val > vmax) vmax = *val;
				if (*val < vmin) vmin = *val;
			}
		}

		_geoTiffImage->setMaxValue(vmax);
		_geoTiffImage->setMinValue(vmin);
	}
}
